package com.z2l2y.start.banner;

import org.springframework.boot.Banner;
import org.springframework.boot.SpringBootVersion;
import org.springframework.boot.ansi.AnsiColor;
import org.springframework.boot.ansi.AnsiOutput;
import org.springframework.boot.ansi.AnsiStyle;
import org.springframework.core.SpringVersion;
import org.springframework.core.env.Environment;

import java.io.PrintStream;
import java.util.*;

/**
 * banner类
 *
 * @author z2l2y
 */
public class Z2l2yBanner implements Banner {

    private static final String DEFAULT_BANNER =
    """          
                      ,----,    ,--,         ,----,
                    .'   .' \\ ,--.'|       .'   .'
           ,----, ,----,'    ||  | :     ,----,'    |
         .'   .`| |    :  .  ;:  : '     |    :  .  ;
      .'   .'  .' ;    |.'  / |  ' |     ;    |.'  /     .--,
    ,---, '   ./  `----'/  ;  '  | |     `----'/  ;    /_ ./|
    ;   | .'  /     /  ;  /   |  | :       /  ;  /  , ' , ' :
    `---' /  ;--,  ;  /  /-,  '  : |__    ;  /  /-,/___/ \\: |
      /  /  / .`| /  /  /.`|  |  | '.'|  /  /  /.`| .  \\  ' |
    ./__;     .'./__;      :  ;  :    ;./__;      :  \\  ;   :
    ;   |  .'   |   :    .'   |  ,   / |   :    .'    \\  \\  ;
    `---'       ;   | .'       ---`-'  ;   | .'        :  \\  \\
                `---'                  `---'            \\  ' ;
                                                         `--`
    """;

    private static final String Z2L2Y = ":: Z2L2Y ::";
    private static final String SPRING_BOOT = ":: Spring Boot ::";
    private static final String SPRING = ":: Spring ::";
    private static final int STRAP_LINE_SIZE = 42;
    private final Map<String, Version> versions = new LinkedHashMap<>();

    private final List<String> encourage = List.of(
            "我从没觉得孤独, 说的浪漫些, 我完全自由.",
            "夕阳总会落在你身上, 你也会快乐一场.",
            "于千万人中获你惊鸿, 从此连生命也愿笑奉.",
            "生活再糟糕, 也不妨碍自己变得更好.",
            "幸与不幸都有尽头.",
            "遇事不决, 可问春风, 春风不语, 即随本心.",
            "希望时光不要轻易地、频繁地抖动, 因为上面依附着所有渺小的众生.",
            "希望你的心情能像星星一样, 常年闪闪发亮, 偶尔躲躲乌云.",
            "向着月亮出发, 即使不能到达, 也能站在群星之中.",
            "不必太纠结于当下, 也不必太忧虑未来, 当你经历过一些事情的时候, 眼前的风景已经和从前不一样了.",
            "有人弃棋, 有人做泥荷做清溪, 有人成为风雨里的一行诗句.",
            "生活如此美好, 忧伤总会逃掉, 既然阳光照耀, 就报之以微笑.",
            "最好的生活就是: 不嫉妒别人, 不看轻自己, 岁月静好, 别来无恙.",
            "月色暗淡还有星辰, 山河失色你还有我.",
            "月色暗淡还有星辰, 山河失色你还有我.",
            "所幸皆为美好, 所行不负年少.",
            "星星温柔泛滥, 人间始终至善.",
            "虽偶有轻风细雨, 但总归晴天朗照.");

    public Z2l2yBanner() {
    }

    @Override
    public void printBanner(Environment environment, Class<?> sourceClass, PrintStream out) {
        // 加载版本信息
        loadVersions(environment, sourceClass);
        // 打印banner
        printBanner(out);
        // 打印版本信息
        printVersions(out);
        // 随机的一句话
        printEnd(out);
    }

    private void printBanner(PrintStream out) {
        out.println(AnsiOutput.toString(AnsiColor.CYAN, DEFAULT_BANNER));
    }

    private void printVersions(PrintStream out) {
        versions.values().forEach(version -> {
            String title = version.title();
            String versionStr = "(v%s)".formatted(version.version());
            StringBuilder padding = new StringBuilder();
            while (padding.length() < STRAP_LINE_SIZE - (versionStr.length() + title.length())) {
                padding.append(" ");
            }
            out.println(AnsiOutput.toString(AnsiColor.CYAN, title, AnsiColor.DEFAULT, padding.toString(),
                    AnsiStyle.FAINT, versionStr));
        });
    }

    private void printEnd(PrintStream out) {
        out.println(AnsiOutput.toString(AnsiColor.CYAN, AnsiStyle.ITALIC, AnsiStyle.UNDERLINE,
                encourage.get(new Random().nextInt(encourage.size()))));
        out.println();
    }

    private void loadVersions(Environment environment, Class<?> sourceClass) {
        versions.putIfAbsent("APPLICATION_VERSION", new Version(Z2L2Y, getApplicationVersion(environment, sourceClass)));
        versions.putIfAbsent("SPRING_BOOT_VERSION", new Version(SPRING_BOOT, SpringBootVersion.getVersion()));
        versions.putIfAbsent("SPRING_VERSION", new Version(SPRING, SpringVersion.getVersion()));
    }

    protected String getApplicationVersion(Environment environment, Class<?> sourceClass) {
        Package sourcePackage = sourceClass != null ? sourceClass.getPackage() : null;
        String version = sourcePackage != null ? sourcePackage.getImplementationVersion() : null;
        if (version == null) {
            version = environment.getProperty("application.version");
        }
        return version;
    }

    private record Version(String title, String version) {

    }
}
